﻿using System.Linq;
using CID.Domain.Development;
using CID.Tests.Support;
using NUnit.Framework;

namespace CID.Domain.Persistence.Tests.Development
{
    [TestFixture]
    class ReleasePersistenceTests : BasePersistenceWithDataTests
    {
        private void AssertAreEqual(Release expected, Release actual)
        {
            Assert.AreEqual(expected.Id, actual.Id);
            Assert.AreEqual(expected.Name, actual.Name);
            Assert.AreEqual(expected.Description, actual.Description);
            Assert.AreEqual(expected.Status, actual.Status);
            Assert.AreEqual(expected.Responsible.Id, actual.Responsible.Id);
            CollectionAssert.AreEquivalent(expected.Versions.Select(x => x.Id).ToArray(), actual.Versions.Select(x => x.Id).ToArray());
        }

        [Test]
        public void PersistNewRelease_ReleaseShouldBeSaved()
        {
            var session = OpenSession();
            var newRelease = DataProvider.CreateRelease(session, UsersData.User1, DevelopmentData.Component1UnreleasedVersion, DevelopmentData.Component2UnreleasedVersion);
            session.SaveOrUpdate(newRelease); 
            CleanSession(session);

            Assert.AreNotEqual(NotSavedId, newRelease.Id);
            session = OpenSession();
            var retrievedRelease = session.Get<Release>(newRelease.Id);
            AssertAreEqual(newRelease, retrievedRelease);
            CleanSession(session);
        }

        [Test]
        public void PersistModifiedRelease_ChangesShouldBeSaved()
        {
            var session = OpenSession();
            var newRelease = DataProvider.CreateRelease(session, UsersData.User1);
            session.SaveOrUpdate(newRelease);
            CleanSession(session);

            session = OpenSession();
            var modifiedRelease = session.Get<Release>(newRelease.Id);
            AssertAreEqual(newRelease, modifiedRelease); //Necessary to get lazy collections before the session gets cleaned
            modifiedRelease.ModifyProperty(x => x.Name);
            modifiedRelease.ModifyProperty(x => x.Description);
            var version = DataProvider.GetVersion(session, DevelopmentData.Component1UnreleasedVersion);
            modifiedRelease.AddVersion(version);
            modifiedRelease.SetReleased();
            CleanSession(session);

            session = OpenSession();
            var retrievedRelease = session.Get<Release>(newRelease.Id);
            AssertAreEqual(modifiedRelease, retrievedRelease);
            CleanSession(session);
        }

        [Test,ExpectedException(typeof(NHibernate.Exceptions.GenericADOException))]
        public void DeleteReleaseWithVersion_ShouldThrowException()
        {
            var session = OpenSession();
            var newRelease1 = DataProvider.CreateRelease(session, UsersData.User1, DevelopmentData.Component1UnreleasedVersion);
            session.SaveOrUpdate(newRelease1);
            CleanSession(session);

            try
            {
                session = OpenSession();
                var retrievedRelease1 = session.Get<Release>(newRelease1.Id);
                session.Delete(retrievedRelease1);
            }
            finally
            {
                CleanSession(session);
            }
        }
    
        [Test]
        public void DeleteReleaseWithNoVersion_ReleaseShouldBeDeleted()
        {
            var session = OpenSession();
            var newRelease1 = DataProvider.CreateRelease(session, UsersData.User1, DevelopmentData.Component1UnreleasedVersion);
            var newRelease2 = DataProvider.CreateRelease(session, UsersData.User2, "Another Release", "Another Release Without Versions");
            session.SaveOrUpdate(newRelease1);
            session.SaveOrUpdate(newRelease2);
            CleanSession(session);

            session = OpenSession();
            var retrievedRelease1 = session.Get<Release>(newRelease1.Id);
            retrievedRelease1.RemoveVersion(retrievedRelease1.Versions.First());
            session.SaveOrUpdate(retrievedRelease1);
            session.Delete(retrievedRelease1);
            CleanSession(session);

            session = OpenSession();
            retrievedRelease1 = session.Get<Release>(newRelease1.Id);
            var retrievedRelease2 = session.Get<Release>(newRelease2.Id);
            Assert.IsNull(retrievedRelease1);
            Assert.IsNotNull(retrievedRelease2);
            CleanSession(session);
        }
    }
}
